package com.da.landlord;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.Executor;
import com.googlecode.cswish.struts.spring.GenericService;
import com.ra.landlord.FeeAdditionRecord;
import com.ra.landlord.FeeRecord;
import com.ra.landlord.FeeRecordService;
import com.ra.landlord.FeeRule;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.FeeRuleCfgDesc;
import com.ra.landlord.FeeRuleCfgDescService;
import com.ra.landlord.FeeRuleCfgService;
import com.ra.landlord.Room;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.order.rental.RentalOrder;
import com.ra.order.rental.RentalOrderService;
import com.ra.system.Version;

/**
 * DA费用项服务
 * @author colin
 * @date 2015年6月11日
 */
@Service
public class DaFeeRuleService {

	@Resource
	private GenericService genericService;
	
	@Resource
	private FeeRuleCfgService feeRuleCfgService;
	
	@Resource
	private FeeRuleCfgDescService feeRuleCfgDescService;
	
	@Resource
	private RentalOrderService rentalOrderService;
	
	@Resource
	private FeeRecordService feeRecordService;
	
	@Resource
	private DaChargeItemService daChargeItemService;
	
	@PersistenceContext(unitName="espirit")
	protected EntityManager em;
	
	private static final Log logger = LogFactory.getLog(DaOwnerService.class);
	
	/**
	 * 新的删除费用规则接口，能够返回哪些费用规则已经被删除
	 * @param model
	 * @return
	 */
	@Rest(type = "delete")
	@Transactional
	public List<Integer> deleteFeeRuleCfg(List<FeeRuleCfg> model) {
		//检查费用规则是否有被用到
		List<Object> delModels = new ArrayList<>();
		List<Integer> delIds = new ArrayList<>();
		//校验，如果该记录已经被使用，则不能被删除，只要有一条被删除，就算删除成功
		if (model != null && model.size() > 0) 
		{
			for (int i = 0; i < model.size(); i++) 
			{
				FeeRuleCfg feeRuleCfg = model.get(i);
				boolean isUsed = feeRuleCfgDescService.checkFeeRuleCfgUsedByRoom(feeRuleCfg);
				if (isUsed)
				{
					logger.warn("该费用已被费用规则使用，不能删除！feeRuleCfg.id=" + feeRuleCfg.getId());
					continue;
				}
				delModels.add(feeRuleCfg);
			}
			if (delModels.size() == 0) {
				throw new ApplicationException("该费用规则已被使用，不能删除！","10001");
			}
			
			genericService.deleteList(delModels);
			
			for (Object object : delModels) 
			{
				FeeRuleCfg temp = (FeeRuleCfg)object;
				delIds.add(temp.getId());
			}
		}
		return delIds;
	}
	
	@Rest(type = "delete")
	@Transactional
	public boolean deleteFeeRuleCfgDesc(List<FeeRuleCfgDesc> model) {
		List<Object> delModel = new ArrayList<>();
		//校验，如果该记录已经被使用，则不能被删除，只要有一条被删除，就算删除成功
		if (model != null && model.size() > 0) {
			FeeRuleCfg feeRuleCfg = new FeeRuleCfg();
			
			for (int i = 0; i < model.size(); i++) {
				FeeRuleCfgDesc feeRuleCfgDesc = model.get(i);
				
				if (feeRuleCfgDesc == null)
				{
					continue;
				}
				
				feeRuleCfg.setFeeRuleCfgDesc(feeRuleCfgDesc);
				List<FeeRuleCfg> lstFeeRuleCfg = feeRuleCfgService.searchMeterFeeRule(feeRuleCfg);
				boolean isUsed = feeRuleCfgDescService.checkFeeRuleCfgsUsedByRoom(lstFeeRuleCfg);
				if (isUsed)
				{
					logger.warn("FeeRuleCfg is used and can not be delete. FeeRuleCfgDesc.id:" + feeRuleCfgDesc.getId());
					continue;
				}
				if (lstFeeRuleCfg != null && lstFeeRuleCfg.size() > 0) 
				{
					List<Integer> deletedCfgIds = deleteFeeRuleCfg(lstFeeRuleCfg);
					if (lstFeeRuleCfg.size() == deletedCfgIds.size()) 
					{
						delModel.add(feeRuleCfgDesc);
					} 
					else 
					{
						logger.warn("该费用项部分计费方式已被费用规则使用，不能删除！feeRuleCfgDesc:" + lstFeeRuleCfg.get(0).getFeeRuleCfgDesc().getId());
					}
					
				}
				else
				{
					delModel.add(feeRuleCfgDesc);
				}
				
			}
			if (delModel.size() == 0) {
				throw new ApplicationException("该收费项已经被使用，不能删除！");
			}
		}
		return genericService.deleteList(delModel);
	}
	
	/**
	 * 删除计费项: 计费项改造.
	 * @param feeDesc
	 * @return
	 * @since v4.0
	 */
	@Rest(type = "delete")
	@Transactional
	public boolean deleteFeeRuleDescCfg(List<String> feeDesc, Boolean cascadeDelete)  
	{
		if (feeDesc != null && feeDesc.size() > 0) 
		{
			for (String feeRuleDesc : feeDesc) 
			{
				String[] ids = feeRuleDesc.split("_");
				Integer descId = Integer.parseInt(ids[0]);
				Integer feeCfgId = Integer.parseInt(ids[1]);
				
				FeeRuleCfgDesc dbFeeRuleCfgDesc = genericService.load(FeeRuleCfgDesc.class, descId);
				FeeRuleCfg dbFeeRuleCfg = genericService.load(FeeRuleCfg.class, feeCfgId);
				if (dbFeeRuleCfgDesc == null || dbFeeRuleCfg == null)
				{
					logger.warn("Invalid data: " + feeDesc);
					throw new ApplicationException("无效的数据！");
				}
				int feeRuleCfgSize = dbFeeRuleCfgDesc.getFeeRuleCfgs().size();
				if (feeRuleCfgSize  == 1) {
					dbFeeRuleCfgDesc.setStatus(Version.STATUS_INVALID);
					dbFeeRuleCfg.setStatus(Version.STATUS_INVALID);
					dbFeeRuleCfg.getFeeRuleCfgCalc().setStatus(Version.STATUS_INVALID);
				} else {
					dbFeeRuleCfg.setStatus(Version.STATUS_INVALID);
					dbFeeRuleCfg.getFeeRuleCfgCalc().setStatus(Version.STATUS_INVALID);
				}
				em.merge(dbFeeRuleCfg);
				final List<DaSuite> daSuites = new ArrayList<DaSuite>(500);
				final List<Room> raRooms = new ArrayList<Room>(500);
				if (cascadeDelete != null && cascadeDelete == true) {
					FeeRule feeRuleExample = new FeeRule();
					feeRuleExample.setFeeRuleCfg(dbFeeRuleCfg);
					feeRuleExample.setStatus(Version.STATUS_VALID);
					List<FeeRule> feeRules = genericService.searchByModel(feeRuleExample, Condition.DEFAULT).getData();
					if (feeRules != null) {
						for (FeeRule feeRule : feeRules) {
							//feeRule.getRoom().getFeeRules().remove(feeRule);
							if (feeRule.getRoom() != null) {
								em.remove(feeRule);
								raRooms.add(feeRule.getRoom());
							} else {
								//分摊，
							}
						}
					}
					
					DaFeeRule daFeeRuleExample = new DaFeeRule();
					daFeeRuleExample.setFeeRuleCfg(dbFeeRuleCfg);
					daFeeRuleExample.setState(1);
					List<DaFeeRule> daFeeRules = genericService.searchByModel(daFeeRuleExample, Condition.DEFAULT).getData();
					if (daFeeRules != null) {
						for (DaFeeRule daFeeRule : daFeeRules) {
							em.remove(daFeeRule);
							if (daFeeRule.getRoom() != null) {
								//daFeeRule.getRoom().getFeeRules().remove(daFeeRule);
								daSuites.add(daFeeRule.getRoom().getSuite());	
							} else if (daFeeRule.getSuite() != null) {
								//daFeeRule.getSuite().getFeeRules().remove(daFeeRule);
								daSuites.add(daFeeRule.getSuite());
							}
							
						}
					}
					em.flush();
					//删除未生成收租单的FeeAdditionRecord，或者已经生成收租单未确认的feeAdditionRecord
					genericService.executeAsync(new Executor<Boolean, FeeRuleCfg>() {
						@Override
						public Boolean execute(FeeRuleCfg feeRuleCfg) {
							deleteNeedPayFeeItem(raRooms, daSuites);
							return Boolean.TRUE;
						}
					}, dbFeeRuleCfg);
					
				}
			}
		}	
		return true;
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void deleteNeedPayFeeItem(List<Room> raRooms, List<DaSuite> daSuites) {
		if (raRooms != null) {
			for (Room room : raRooms) {
				try {
					feeRecordService.repairedFeeRecordByRoom(room);
				} catch (Exception e) {
					logger.error("级联删除费用项已经产生的收费失败！room Id:" + room.getId() , e);
				}	
			}
		}
		
		if (daSuites != null) {
			for (DaSuite suite : daSuites) {
				try {
					daChargeItemService.repaireFixedChargeItem(suite);
				} catch (Exception e) {
					logger.error("级联删除费用项已经产生的收费失败！suite Id:" + suite.getId(), e);
				}	
			}
		}
		
	}
	
	/**
	 * 确定房源下所有的固定费用
	 * @param suite
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfg> searchFixedFeeRule(DaSuite suite){
		suite = genericService.load(suite);
		List<DaFeeRule> feeRules = suite.getFeeRules();
		List<FeeRuleCfg> result = null;
		for ( DaFeeRule daFeeRule : feeRules ) {
			FeeRuleCfg cfg = daFeeRule.getFeeRuleCfg();
			if( cfg != null && cfg.getFeeRuleCfgDesc().getType() == FeeRuleType.fixed ){
				if( result == null )
					result = new ArrayList<FeeRuleCfg>();
				result.add(cfg);
			}
		}
		
		return result;
	}
	
}
